widget: Parent widgets may also consume motions
authorTimm Bäder <mail@baedert.org>
Wed, 21 Nov 2018 16:51:10 +0000 (17:51 +0100)
committerTimm Bäder <mail@baedert.org>
Tue, 27 Nov 2018 04:37:38 +0000 (05:37 +0100)
This is important when the target widget of an event is not the one that
would otherwise receive the gesture. For example, the GtkSwitch
implementation currently attaches a pan gesture to the switch itself,
but the target widget below the pointer might be the switch slider or
label.

See #1465

gtk/gtkwidget.c

index 587bf81b0fd5b02ca5215aae4a7f70a6c4eda07b..eeb5bc6423ed9bbd176d07a041b9289e187a3474 100644 (file)
@@ -12925,23 +12925,28 @@ _gtk_widget_consumes_motion (GtkWidget        *widget,
                              GdkEventSequence *sequence)
 {
   GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
-  GList *l;
-
-  g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
 
-  for (l = priv->event_controllers; l; l = l->next)
+  while (widget != NULL && !GTK_IS_WINDOW (widget))
     {
-      GtkEventController *controller = l->data;
+      GList *l;
 
-      if (controller == NULL ||
-          !GTK_IS_GESTURE (controller))
-        continue;
+      for (l = priv->event_controllers; l; l = l->next)
+        {
+          GtkEventController *controller = l->data;
 
-      if ((!GTK_IS_GESTURE_SINGLE (controller) ||
-           GTK_IS_GESTURE_DRAG (controller) ||
-           GTK_IS_GESTURE_SWIPE (controller)) &&
-          gtk_gesture_handles_sequence (GTK_GESTURE (controller), sequence))
-        return TRUE;
+          if (controller == NULL ||
+              !GTK_IS_GESTURE (controller))
+            continue;
+
+          if ((!GTK_IS_GESTURE_SINGLE (controller) ||
+               GTK_IS_GESTURE_DRAG (controller) ||
+               GTK_IS_GESTURE_SWIPE (controller)) &&
+              gtk_gesture_handles_sequence (GTK_GESTURE (controller), sequence))
+            return TRUE;
+        }
+
+      widget = priv->parent;
+      priv = gtk_widget_get_instance_private (widget);
     }
 
   return FALSE;